#include "widget.h"
#include "ui_widget.h"
#include "xsharedptr.h"

#include <iostream>
#include  <memory>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    test_uniqueptr();
    //test_xsharedptr();
    //test_sharedptr();

}

Widget::~Widget()
{
    delete ui;
}

void Widget::test_uniqueptr()
{
//    std::unique_ptr<int> p1(new int(10));
//    std::unique_ptr<int> p2;

//    // 不支持拷贝和赋值
//    p2 = p1; // 编译器报错
//    unique_ptr<int> p3(p1); // 编译器报错

//    // 将P1指针的所有权转移给p4，转以后p1为nullptr
//    std::unique_ptr<int> p4 = std::move(p1);


    // 指针的创建
//    // 创建一个空指针对象，此时ptr1为nullptr
//    std::unique_ptr<int> ptr1;
//    // 构造函数创建
//    std::unique_ptr<int> ptr2(new int(10));
//    // 使用make_unique创建(c++14版本开始支持)
//    std::unique_ptr<int> ptr3 = std::make_unique<int>(10);
//    auto ptr4 = std::make_unique<int>(10);

    // 指针的使用
    // get() 返回关联指针


    // 指针的判断空
//    // 方法1
//    if(!ptr1)
//        std::cout<<"ptr1 is empty"<<std::endl;
//    // 方法2
//    if(ptr1 == nullptr)
//        std::cout<<"ptr1 is empty"<<std::endl;

    // 指针的释放和销毁

    // 函数说明
    // release(): 不delete关联指针，只释放关联指针的所有权，并返回关联指针，之后unique_ptr为空
    // reset():   重置unique_ptr为空，delete其关联的指针

    // 释放关联指针的所有权
    std::unique_ptr<int> p1(new int(10));
    int * ptr = p1.release();
    if(p1 == nullptr)
        std::cout<<"p1 is empty"<<std::endl;
    // 此时需要手动是否关联指针
    delete ptr;
    ptr = nullptr;

    // 重置unique_ptr
    std::unique_ptr<int> p2(new int(10));
    p2.reset();
    // p2为空
    if(p1 == nullptr)
        std::cout<<"p1 is empty"<<std::endl;


    // 指针的转移
//    // 通过std::move()转移
//    std::unique_ptr<int> ptr2(new int(10));
//    std::unique_ptr<int> taskPtr4 = std::move(taskPtr2);
//    // 现在taskPtr2关联的指针为空
//    if(taskPtr2 == nullptr)
//        std::cout<<"taskPtr2 is  empty"<<std::endl;


}

void Widget::test_xsharedptr()
{
    QString *str1 = new QString("str1");
    qDebug() << "str1:" << str1;

    XSharedPtr<QString> str1_p1(str1);
    XSharedPtr<QString> str1_p2(str1_p1);

    XSharedPtr<QString> str1_p3;
    str1_p3 = str1_p1;
}

void Widget::test_sharedptr()
{
    // 使用 make_shared 创建空对象
    std::shared_ptr<int> p1 = std::make_shared<int>();
    std::cout << p1 << p1.get() << std::endl;

    *p1 = 78;
    std::cout << "p1 = " << *p1 << std::endl; // 输出78

    // 打印引用个数：1
    std::cout << "p1 Reference count = " << p1.use_count() << std::endl;

    // 第2个 shared_ptr 对象指向同一个指针
    std::shared_ptr<int> p2(p1);

    // 下面两个输出都是：2
    std::cout << "p2 Reference count = " << p2.use_count() << std::endl;
    std::cout << "p1 Reference count = " << p1.use_count() << std::endl;

    // 比较智能指针，p1 等于 p2
    if (p1 == p2) {
        std::cout << "p1 and p2 are pointing to same pointer\n";
    }

    std::cout<<"Reset p1 "<<std::endl;

    // 无参数调用reset，无关联指针，引用个数为0
    p1.reset();
    std::cout << "p1 Reference Count = " << p1.use_count() << std::endl;

    // 带参数调用reset，引用个数为1
    p1.reset(new int(11));
    std::cout << "p1 Reference Count = " << p1.use_count() << std::endl;

    // 把对象重置为NULL，引用计数为0
    p1 = nullptr;
    std::cout << "p1 Reference Count = " << p1.use_count() << std::endl;
    if (!p1) {
        std::cout << "p1 is NULL" << std::endl; // 输出
    }
}

